package com.atguigu.gmall.order.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.common.constans.MqConst;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.service.RabbitService;
import com.atguigu.gmall.common.util.HttpClient;
import com.atguigu.gmall.common.util.HttpClientUtil;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.enums.OrderStatus;
import com.atguigu.gmall.model.enums.ProcessStatus;
import com.atguigu.gmall.model.order.OrderDetail;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.order.mapper.CartInfoMapper;
import com.atguigu.gmall.order.mapper.OrderDetailMapper;
import com.atguigu.gmall.order.mapper.OrderInfoMapper;
import com.atguigu.gmall.order.service.OrderInfoService;
import com.atguigu.gmall.product.client.ProductFeignClient;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.cache.CacheProperties;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class OrderInfoServiceImpl implements OrderInfoService {

    @Value("${ware.url}")
    private String wareUrl;
    @Autowired
    private OrderInfoMapper orderInfoMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private ProductFeignClient productFeignClient;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private CartInfoMapper cartInfoMapper;
    //校验商品是否还有库存 ，库存定义：购买数量大于剩余库存数量 数位库存不足
    @Override
    public Boolean hasStock(Long skuId, Integer skuNum) {
        return "1".equals(HttpClientUtil.
                doGet(wareUrl + "/hasStock?skuId=" + skuId + "&num=" + skuNum));
    }

    /**
     * 保存订单
     * @param orderInfo
     * @return
     */
    @Override
    public Long saveOrderInfo(OrderInfo orderInfo) {
        //3：保存订单 订单详情表 设计
        //3.2 订单状态
        orderInfo.setOrderStatus(OrderStatus.UNPAID.name());
        //3.3订单交易编号（将来第三方支付唯一ID）
        String out_trade_no = "ATGUIGU"+System.currentTimeMillis()+new Random().nextInt(1000);
        orderInfo.setOutTradeNo(out_trade_no);
        //3.4：付钱的时候 显示名称
        StringBuilder sb = new StringBuilder();
        List<OrderDetail> orderDetailList =
                orderInfo.getOrderDetailList();
        for (OrderDetail orderDetail : orderDetailList) {
            sb.append(orderDetail.getSkuName()).append(" ");
            //订单详情OrderDetail 中的价格要求实时价格 重新查询 不相信页面传过来的价格
            BigDecimal price = productFeignClient.getPrice(orderDetail.getSkuId());
            orderDetail.setOrderPrice(price);
        }
        if (sb.length()>100){
            orderInfo.setTradeBody(sb.substring(0,100));
        }else {
            orderInfo.setTradeBody(sb.toString());
        }
        //3.5 创建时间
        Calendar calendar = Calendar.getInstance();
        orderInfo.setCreateTime(calendar.getTime());
        //3.6 失效时间
        calendar.add(Calendar.HOUR,2);
        orderInfo.setExpireTime(calendar.getTime());
        //3,7进度状态
        orderInfo.setProcessStatus(ProcessStatus.UNPAID.name());
        //3.8金额
        orderInfo.sumTotalAmount();//计算总金额
        //保存订单表
        orderInfoMapper.insert(orderInfo);


        List<String> skuIdList = new ArrayList<>();
        //4 保存订单详情
        orderDetailList.stream().forEach(orderDetail -> {
            orderDetail.setOrderId(orderInfo.getId());
            orderDetailMapper.insert(orderDetail);
            skuIdList.add(orderDetail.getSkuId().toString());
        });
        //5. 删除Redis 购物车中已经 购买了的商品
        String cartInfoCacheKey =
                RedisConst.USER_KEY_PREFIX+orderInfo.getUserId()+RedisConst.USER_CART_KEY_SUFFIX;
        redisTemplate.opsForHash().delete(cartInfoCacheKey,skuIdList.toArray());

        //删除DB  delete from cart_info where sku_id in (8，15) and user_id = 3

        //1:
   /*     cartInfoMapper.delete(new QueryWrapper<CartInfo>()
           .in("sku_id",skuIdList.toArray())
                .eq("user_id",orderInfo.getUserId()));*/
        //2:
  /*      cartInfoMapper.delete(new QueryWrapper<CartInfo>()
           .lambda().in(CartInfo::getSkuId,skuIdList.toArray())
            .eq(CartInfo::getUserId,orderInfo.getUserId()));*/
        //3:
        cartInfoMapper.delete(new LambdaQueryWrapper<CartInfo>()
                .in(CartInfo::getSkuId,skuIdList.toArray())
                .eq(CartInfo::getUserId,orderInfo.getUserId()));

        // 5: 开始计时 2小时 之后  用户不给钱  取消订单  计时器 MQ的延迟消息
//        rabbitService.sendDelayMessage(MqConst.EXCHANGE_DIRECT_ORDER_CANCEL,
//                MqConst.ROUTING_ORDER_CANCEL,orderInfo.getId(),MqConst.DELAY_TIME);
       return orderInfo.getId();

    }

    ////取消订单  注意：幂等性问题
    @Override
    public void cancelOrder(Long orderId) {
        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
        if (OrderStatus.UNPAID.name().equals(orderInfo.getOrderStatus())){
            //才可以取消订单
            orderInfo.setOrderStatus(OrderStatus.CLOSED.name());
            orderInfo.setProcessStatus(ProcessStatus.CLOSED.name());
            orderInfoMapper.updateById(orderInfo);
            System.out.println("可以取消订单");
        }else {
            System.out.println("不可以取消订单");
        }
    }

    //查询订单的对象
    @Override
    public OrderInfo getOrderInfo(Long orderId) {
        QueryWrapper<OrderInfo> orderInfoQueryWrapper = new QueryWrapper<>();
        orderInfoQueryWrapper.lambda().eq(OrderInfo::getId,orderId)
                .select(OrderInfo::getTotalAmount,OrderInfo::getId);
        return orderInfoMapper.selectOne(orderInfoQueryWrapper);
    }

    //更新订单状态
    @Override
    public void updateOrderStatus(Long orderId, ProcessStatus processStatus) {
        OrderInfo orderInfo = new OrderInfo();
        //ID
        orderInfo.setId(orderId);
        //订单状态
        orderInfo.setOrderStatus(processStatus.getOrderStatus().name());
        //进度状态
        orderInfo.setOrderStatus(processStatus.name());
        orderInfoMapper.updateById(orderInfo);


    }

    //开始拆单   代码巅峰
    @Override
    public List<OrderInfo> orderSplit(Long orderId, String wareSkuMap) {
        //1:原订单
        OrderInfo originOrderInfo = getOrderInfoAndDetail(orderId);
        //2:将wareSkuMap 转成集合
        List<Map> mapList = JSONObject.parseArray(wareSkuMap,Map.class);
        //返回值就是子订单集合
        List<OrderInfo> subOrderInfoList = mapList.stream().map(map -> {
            //子订单
            OrderInfo subOrderInfo = new OrderInfo();
            //将仓库编号传递给子订单
            subOrderInfo.setWareId(String.valueOf(map.get("wareId")));

            //大多数信息是一样的
            BeanUtils.copyProperties(originOrderInfo,subOrderInfo);
            //2.1 设置子订单的主键位null
            subOrderInfo.setId(null);// 将来保存到DB中 由DB 自增长产生
            //2.2 子订单的父订单ID 是原订单的主键
            subOrderInfo.setParentOrderId(originOrderInfo.getId());

            //2.3 子订单总金额是不一样的
            //   [
            //      {"wareId":"2","skuIds":["1","8"]},     一个仓库 代表一个包裹 代表一张订单
            //      {"wareId":"1","skuIds":["2","5"]}
            //    ]
            List<String> skuIdList = (List<String>) map.get("skuIds");
            //原订单明细
            List<OrderDetail> originOrderDetailList = originOrderInfo.getOrderDetailList();
            //子订单明细
            List<OrderDetail> subOrderDetailList = originOrderDetailList.stream().filter(orderDetail -> {
                if (skuIdList.contains(String.valueOf(orderDetail.getSkuId()))){
                    //包含就要
                    return  true;
                }
                //不包含就不要
                return  false;
            }).collect(Collectors.toList());
            subOrderInfo.setOrderDetailList(subOrderDetailList);
            //计算总金额
            subOrderInfo.sumTotalAmount();
            //2.4:保存子订单的
            orderInfoMapper.insert(subOrderInfo);
            //2.5:更新子订单的明细（外键 子订单的主键）
            subOrderDetailList.forEach(orderDetail -> {
                //外键就是子订单的主键
                orderDetail.setOrderId(subOrderInfo.getId());
                orderDetailMapper.updateById(orderDetail);
            });
            return subOrderInfo;
        }).collect(Collectors.toList());
        //3、 更新原订单的状态 进度状态  为 订单已拆分
        updateOrderStatus(orderId,ProcessStatus.SPLIT);
       //
        return subOrderInfoList;

    }

    @Override
    public Map initWareData(OrderInfo orderInfo) {
        Map map = new HashMap();
        map.put("orderId", orderInfo.getId());//订单ID
        map.put("consignee", orderInfo.getConsignee());//收货人
        map.put("consigneeTel", orderInfo.getConsigneeTel());//电话
        map.put("orderComment", orderInfo.getOrderComment());
        map.put("orderBody", orderInfo.getTradeBody());
        map.put("deliveryAddress", orderInfo.getDeliveryAddress());
        map.put("wareId", orderInfo.getWareId());//扩展一个仓库编号
        // 支付方式 ：  1为货到付款  2：在线支付
        map.put("paymentWay", "ONLINE".equals(orderInfo.getPaymentWay())?"2":"1");

        List<Map> details = orderInfo.getOrderDetailList().stream().map(orderDetail -> {
            Map m = new HashMap();
            m.put("skuId",orderDetail.getSkuId());
            m.put("skuNum",orderDetail.getSkuNum());
            m.put("skuName",orderDetail.getSkuName());
            return m;
        }).collect(Collectors.toList());
        //明细
        map.put("details", details);
        return map;

    }


    //查询订单对象 及订单明细对象集合
    public OrderInfo getOrderInfoAndDetail(Long orderId){
        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
        //当前订单的明细集合
        List<OrderDetail> orderDetailList = orderDetailMapper.selectList(new LambdaQueryWrapper<OrderDetail>()
                .eq(OrderDetail::getOrderId, orderId));
        orderInfo.setOrderDetailList(orderDetailList);
        return orderInfo;
    }
    //构建发给仓库系统的Map数据
    public Map initWareData(Long orderId){
        OrderInfo orderInfo = getOrderInfoAndDetail(orderId);
       return initWareData(orderInfo);
    }


}
